# 这是一个示例 Python 脚本。

# 按 Shift+F10 执行或将其替换为您的代码。
# 按 双击 Shift 在所有地方搜索类、文件、工具窗口、操作和设置。


# -*- coding:utf-8 -*-
# !/usr/bin/env python
import tensorflow.compat.v1 as tf  # tensorflowv1和v2很多不兼容，并且不能够支持运行时计算
import os
import input_data

os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3'


def bp_neural():
    tf.disable_eager_execution()
    mnist_data = input_data.read_data_sets("./MNIST_data", one_hot=True)
    train_data = mnist_data.train
    validation_data = mnist_data.validation
    test_data = mnist_data.test

    # 以下是传统的bp神经网络，使用卷积神经网络需要先使用卷积加上池化然后输入结果到bp神经网络中
    # 各层节点个数
    input_n = 784  # 28*28,将图片每个像素进行输入
    output_n = 10
    hidden_n = 100  # 只有一个隐层，一个隐层里有25个神经元

    # 输入，输出占位
    x_ = tf.placeholder(tf.float32, shape=[None, input_n])
    y_ = tf.placeholder(tf.float32, shape=[None, output_n])

    # 权值矩阵和阈值
    w1 = tf.Variable(tf.random_normal([input_n, hidden_n], stddev=0.1))  # stddev是正态分布的标准差,依照标准差函数随机选取若干值形成一个符合形状的张量作为权重
    b1 = tf.Variable(tf.random_normal([1, hidden_n], stddev=0.1))
    y1 = tf.nn.sigmoid(tf.matmul(x_, w1) + b1)

    w2 = tf.Variable(tf.random_normal([hidden_n, hidden_n], stddev=0.1))
    b2 = tf.Variable(tf.random_normal([1, hidden_n], stddev=0.1))
    y2 = tf.nn.sigmoid(tf.matmul(y1, w2) + b2)

    wf = tf.Variable(tf.random_normal([hidden_n, output_n], stddev=0.1))
    bf = tf.Variable(tf.random_normal([1, output_n], stddev=0.1))

    # 选择sigmoid函数

    # matrix_yi = tf.nn.sigmoid(tf.matmul(x_, w1) + b1)  # 每一层的计算
    final_opt = tf.nn.sigmoid(tf.matmul(y2, wf) + bf)  # 倒数第二层和最后一层计算和其他层不一样

    # relu函数
    # hidden_op = tf.nn.relu(tf.matmul(x, w1) + b1)
    # final_opt = tf.nn.relu(tf.matmul(hidden_op, w2) + b2)

    # 对输出层计算交叉熵损失（可以使用方差，本质上都是在计算熵）
    loss_fun = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits_v2(labels=y_, logits=final_opt))
    opt = tf.train.GradientDescentOptimizer(0.3).minimize(loss_fun)  # 学习率：过大会震荡，过小会导致收敛过慢
    # 计算准确率
    correct_pred = tf.equal(tf.argmax(final_opt, 1), tf.argmax(y_, 1))
    accuracy = tf.reduce_mean(tf.cast(correct_pred, tf.float32))
    # 初始化变量
    init = tf.global_variables_initializer()

    train_is_no = True
    with tf.Session() as session:
        session.run(init)
        if train_is_no:
            for i in range(55000):
                # 每次选择100个样本进行训练
                batch_xs, batch_ys = train_data.next_batch(100)
                # test_batch_xs, test_batch_ys = test_data.next_batch(100)
                opt.run({x_: batch_xs, y_: batch_ys})
                if i % 50 == 0:
                    train_accuracy = accuracy.eval({x_: train_data.images, y_: train_data.labels})
                    test_accuracy = accuracy.eval({x_: test_data.images, y_: test_data.labels})
                    print("step %d, training accuracy %g , test accuracy %.4f" % (i, train_accuracy, test_accuracy))

            # 计算模型在测试集上的准确率
            print("test accuracy %.4f" % accuracy.eval({x_: test_data.images, y_: test_data.labels}))


def main():
    bp_neural()


if __name__ == '__main__':
    main()

# 访问 https://www.jetbrains.com/help/pycharm/ 获取 PyCharm 帮助
